struct _GtkCssSelectorClass {
const char *name;
- void (* print) (const GtkCssSelector *selector,
- GString *string);
- gboolean (* match) (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher);
+ void (* print) (const GtkCssSelector *selector,
+ GString *string);
+ gboolean (* match) (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher);
+ GtkCssChange (* get_change) (const GtkCssSelector *selector);
guint increase_id_specificity :1;
guint increase_class_specificity :1;
return selector->class->match (selector, matcher);
}
+static GtkCssChange
+gtk_css_selector_get_change (const GtkCssSelector *selector)
+{
+ if (selector == NULL)
+ return 0;
+
+ return selector->class->get_change (selector);
+}
+
static const GtkCssSelector *
gtk_css_selector_previous (const GtkCssSelector *selector)
{
return FALSE;
}
+static GtkCssChange
+gtk_css_selector_descendant_get_change (const GtkCssSelector *selector)
+{
+ return _gtk_css_change_for_child (gtk_css_selector_get_change (gtk_css_selector_previous (selector)));
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
"descendant",
gtk_css_selector_descendant_print,
gtk_css_selector_descendant_match,
+ gtk_css_selector_descendant_get_change,
FALSE, FALSE, FALSE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), &parent);
}
+static GtkCssChange
+gtk_css_selector_child_get_change (const GtkCssSelector *selector)
+{
+ return _gtk_css_change_for_child (gtk_css_selector_get_change (gtk_css_selector_previous (selector)));
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
"child",
gtk_css_selector_child_print,
gtk_css_selector_child_match,
+ gtk_css_selector_child_get_change,
FALSE, FALSE, FALSE
};
return FALSE;
}
+static GtkCssChange
+gtk_css_selector_sibling_get_change (const GtkCssSelector *selector)
+{
+ return _gtk_css_change_for_sibling (gtk_css_selector_get_change (gtk_css_selector_previous (selector)));
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
"sibling",
gtk_css_selector_sibling_print,
gtk_css_selector_sibling_match,
+ gtk_css_selector_sibling_get_change,
FALSE, FALSE, FALSE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), &previous);
}
+static GtkCssChange
+gtk_css_selector_adjacent_get_change (const GtkCssSelector *selector)
+{
+ return _gtk_css_change_for_sibling (gtk_css_selector_get_change (gtk_css_selector_previous (selector)));
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
"adjacent",
gtk_css_selector_adjacent_print,
gtk_css_selector_adjacent_match,
+ gtk_css_selector_adjacent_get_change,
FALSE, FALSE, FALSE
};
return gtk_css_selector_match (previous, matcher);
}
+static GtkCssChange
+gtk_css_selector_any_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector));
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = {
"any",
gtk_css_selector_any_print,
gtk_css_selector_any_match,
+ gtk_css_selector_any_get_change,
FALSE, FALSE, FALSE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
+static GtkCssChange
+gtk_css_selector_name_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_NAME;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = {
"name",
gtk_css_selector_name_print,
gtk_css_selector_name_match,
+ gtk_css_selector_name_get_change,
FALSE, FALSE, TRUE
};
return gtk_css_selector_match (previous, matcher);
}
+static GtkCssChange
+gtk_css_selector_region_get_change (const GtkCssSelector *selector)
+{
+ GtkCssChange change;
+
+ change = gtk_css_selector_get_change (gtk_css_selector_previous (selector));
+ change |= GTK_CSS_CHANGE_REGION;
+ change |= _gtk_css_change_for_child (change);
+
+ return change;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_REGION = {
"region",
gtk_css_selector_region_print,
gtk_css_selector_region_match,
+ gtk_css_selector_region_get_change,
FALSE, FALSE, TRUE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
+static GtkCssChange
+gtk_css_selector_class_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_CLASS;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CLASS = {
"class",
gtk_css_selector_class_print,
gtk_css_selector_class_match,
+ gtk_css_selector_class_get_change,
FALSE, TRUE, FALSE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
+static GtkCssChange
+gtk_css_selector_id_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_ID;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ID = {
"id",
gtk_css_selector_id_print,
gtk_css_selector_id_match,
+ gtk_css_selector_id_get_change,
TRUE, FALSE, FALSE
};
return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
+static GtkCssChange
+gtk_css_selector_pseudoclass_state_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_STATE;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_STATE = {
"pseudoclass-state",
gtk_css_selector_pseudoclass_state_print,
gtk_css_selector_pseudoclass_state_match,
+ gtk_css_selector_pseudoclass_state_get_change,
FALSE, TRUE, FALSE
};
return gtk_css_selector_match (previous, matcher);
}
+static GtkCssChange
+gtk_css_selector_pseudoclass_region_get_change (const GtkCssSelector *selector)
+{
+ return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_POSITION;
+}
+
static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_REGION = {
"pseudoclass-region",
gtk_css_selector_pseudoclass_region_print,
gtk_css_selector_pseudoclass_region_match,
+ gtk_css_selector_pseudoclass_region_get_change,
FALSE, TRUE, FALSE
};
return g_string_free (string, FALSE);
}
+GtkCssChange
+_gtk_css_selector_get_change (const GtkCssSelector *selector)
+{
+ g_return_val_if_fail (selector != NULL, 0);
+
+ return gtk_css_selector_get_change (selector);
+}
+
/**
* _gtk_css_selector_matches:
* @selector: the selector
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderImageRepeat, _gtk_css_border_image_repeat)
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssNumber, _gtk_css_number)
+typedef struct _GtkCssChangeTranslation GtkCssChangeTranslation;
+struct _GtkCssChangeTranslation {
+ GtkCssChange from;
+ GtkCssChange to;
+};
+
+static GtkCssChange
+gtk_css_change_translate (GtkCssChange match,
+ const GtkCssChangeTranslation *translations,
+ guint n_translations)
+{
+ GtkCssChange result = match;
+ guint i;
+
+ for (i = 0; i < n_translations; i++)
+ {
+ if (match & translations[i].from)
+ {
+ result &= ~translations[i].from;
+ result |= translations[i].to;
+ }
+ }
+
+ return result;
+}
+
+GtkCssChange
+_gtk_css_change_for_sibling (GtkCssChange match)
+{
+ static const GtkCssChangeTranslation table[] = {
+ { GTK_CSS_CHANGE_CLASS, GTK_CSS_CHANGE_SIBLING_CLASS },
+ { GTK_CSS_CHANGE_NAME, GTK_CSS_CHANGE_SIBLING_NAME },
+ { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_SIBLING_POSITION },
+ { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_SIBLING_STATE },
+ };
+
+ return gtk_css_change_translate (match, table, G_N_ELEMENTS (table));
+}
+
+GtkCssChange
+_gtk_css_change_for_child (GtkCssChange match)
+{
+ static const GtkCssChangeTranslation table[] = {
+ { GTK_CSS_CHANGE_CLASS, GTK_CSS_CHANGE_PARENT_CLASS },
+ { GTK_CSS_CHANGE_NAME, GTK_CSS_CHANGE_PARENT_NAME },
+ { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_PARENT_POSITION },
+ { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_PARENT_STATE },
+ { GTK_CSS_CHANGE_SIBLING_CLASS, GTK_CSS_CHANGE_PARENT_SIBLING_CLASS },
+ { GTK_CSS_CHANGE_SIBLING_NAME, GTK_CSS_CHANGE_PARENT_SIBLING_NAME },
+ { GTK_CSS_CHANGE_SIBLING_POSITION, GTK_CSS_CHANGE_PARENT_SIBLING_POSITION },
+ { GTK_CSS_CHANGE_SIBLING_STATE, GTK_CSS_CHANGE_PARENT_SIBLING_STATE }
+ };
+
+ return gtk_css_change_translate (match, table, G_N_ELEMENTS (table));
+}
+
void
_gtk_css_number_init (GtkCssNumber *number,
double value,
G_BEGIN_DECLS
+typedef enum { /*< skip >*/
+ GTK_CSS_CHANGE_CLASS = (1 << 0),
+ GTK_CSS_CHANGE_NAME = (1 << 1),
+ GTK_CSS_CHANGE_ID = GTK_CSS_CHANGE_NAME,
+ GTK_CSS_CHANGE_REGION = GTK_CSS_CHANGE_NAME,
+ GTK_CSS_CHANGE_POSITION = (1 << 2),
+ GTK_CSS_CHANGE_STATE = (1 << 3),
+ GTK_CSS_CHANGE_SIBLING_CLASS = (1 << 4),
+ GTK_CSS_CHANGE_SIBLING_NAME = (1 << 5),
+ GTK_CSS_CHANGE_SIBLING_POSITION = (1 << 6),
+ GTK_CSS_CHANGE_SIBLING_STATE = (1 << 7),
+ GTK_CSS_CHANGE_PARENT_CLASS = (1 << 8),
+ GTK_CSS_CHANGE_PARENT_NAME = (1 << 9),
+ GTK_CSS_CHANGE_PARENT_POSITION = (1 << 10),
+ GTK_CSS_CHANGE_PARENT_STATE = (1 << 11),
+ GTK_CSS_CHANGE_PARENT_SIBLING_CLASS = (1 << 12),
+ GTK_CSS_CHANGE_PARENT_SIBLING_NAME = (1 << 13),
+ GTK_CSS_CHANGE_PARENT_SIBLING_POSITION = (1 << 14),
+ GTK_CSS_CHANGE_PARENT_SIBLING_STATE = (1 << 15),
+ /* add more */
+} GtkCssChange;
+
+#define GTK_CSS_CHANGE_ANY ((1 << 16) - 1)
+#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE)
+#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_SIBLING_CLASS | GTK_CSS_CHANGE_SIBLING_NAME | \
+ GTK_CSS_CHANGE_SIBLING_POSITION | GTK_CSS_CHANGE_SIBLING_STATE)
+#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_PARENT_CLASS | GTK_CSS_CHANGE_PARENT_SIBLING_CLASS | \
+ GTK_CSS_CHANGE_PARENT_NAME | GTK_CSS_CHANGE_PARENT_SIBLING_NAME | \
+ GTK_CSS_CHANGE_PARENT_POSITION | GTK_CSS_CHANGE_PARENT_SIBLING_POSITION | \
+ GTK_CSS_CHANGE_PARENT_STATE | GTK_CSS_CHANGE_PARENT_SIBLING_STATE)
+
typedef enum {
GTK_CSS_INHERIT,
GTK_CSS_INITIAL
GType _gtk_css_border_image_repeat_get_type (void);
GType _gtk_css_number_get_type (void);
+GtkCssChange _gtk_css_change_for_sibling (GtkCssChange match);
+GtkCssChange _gtk_css_change_for_child (GtkCssChange match);
+
#define GTK_CSS_NUMBER_INIT(_value,_unit) { (_value), (_unit) }
void _gtk_css_number_init (GtkCssNumber *number,
double value,